#include "common.h"
#include "Stream.h"
#include "memoryDef.h"


CRawFile::CRawFile()
:m_file(NULL)
{
}

CRawFile::~CRawFile()
{
	Close();
}

bool CRawFile::Open(const char *fn, int mode)
{	
	if((mode & MODE_CREATE) || (mode & MODE_WRITE))
	{
		m_file = fopen(fn, "wb");
	}
	else if(mode & MODE_APPEND)
	{
		m_file = fopen(fn, "ab");
	}
	else
	{
		m_file = fopen(fn, "rb");
	}

	return m_file != NULL;
}

void CRawFile::Close()
{
	if(m_file)
	{
		fclose(m_file);
		m_file = NULL;
	}
}

bool CRawFile::Seek(int moveDistance, int seekMode)
{
	int o;
	if(seekMode == FSEEK_BEGIN)
		o = SEEK_SET ;
	else if(seekMode == FSEEK_CURRENT)
		o = SEEK_CUR;
	else if(seekMode == FSEEK_END)
		o = SEEK_END;
	else
	{
		assert(false);
		return false;
	}

	return fseek(m_file, moveDistance, o) == 0;
}

unsigned int CRawFile::GetLength()
{
	if(m_file == NULL)
	{
		return 0;
	}
	long orgPos = ftell(m_file);
	fseek(m_file, 0, SEEK_END);
	long fl = ftell(m_file);
	fseek(m_file, orgPos, SEEK_SET);
	return fl;
}

unsigned int CRawFile::GetPosition()
{
	return ftell(m_file);
}

unsigned int CRawFile::Write(const void *buf, unsigned int size)
{
	return fwrite(buf, 1, size, m_file);
}

unsigned int CRawFile::Read(void *buf, unsigned int size)
{
	return fread(buf, 1, size, m_file);
}

CFileStream::CFileStream()
{
}

CFileStream::~CFileStream()
{
}

bool CFileStream::Open(const char* pName, int mode)
{
	m_mode = mode;
	if(!m_file.Open(pName, mode))
		return false;
	return true;
}
int CFileStream::GetLength()
{
	return m_file.GetLength();
}

int CFileStream::GetPosition()
{
	return m_file.GetPosition();
}

bool CFileStream::SetPosition(int pos)
{
	return m_file.Seek(pos, CRawFile::FSEEK_BEGIN);
}

bool CFileStream::Skip(int pos)
{
	return m_file.Seek(pos, CRawFile::FSEEK_CURRENT);
}

bool CFileStream::IsReadOnly()
{
	return m_mode == CRawFile::MODE_READ;
}

int CFileStream::Read(void* pBuffer, int length)
{
	return m_file.Read(pBuffer, length);
}

signed char CFileStream::ReadByte()
{
	signed char c;
	int ret = m_file.Read(&c, 1);
	assert(ret == 1);
	return c;
}

unsigned char CFileStream::ReadUByte()
{
	unsigned char c;
	int ret = m_file.Read(&c, 1);
	assert(ret == 1);
	return c;
}

short CFileStream::ReadShortLE()
{
	unsigned char c[2];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (short)((c[1] << 8) | c[0]);
}

unsigned short CFileStream::ReadUShortLE()
{
	unsigned char c[2];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (unsigned short)((c[1] << 8) | c[0]);
}

int CFileStream::ReadIntLE()
{
	unsigned char c[4];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
}

unsigned int CFileStream::ReadUIntLE()
{
	unsigned char c[4];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
}

short CFileStream::ReadShortBE()
{
	unsigned char c[2];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (short)((c[0] << 8) | c[1]);
}

unsigned short CFileStream::ReadUShortBE()
{
	unsigned char c[2];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (unsigned short)((c[0] << 8) | c[1]);
}

int CFileStream::ReadIntBE()
{
	unsigned char c[4];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}

unsigned int CFileStream::ReadUIntBE()
{
	unsigned char c[4];
	int ret = m_file.Read(&c, sizeof(c));
	assert(ret == sizeof(c));
	return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}

int CFileStream::Write(const void* pBuffer, int length)
{
	return m_file.Write(pBuffer, length);
}

void CFileStream::WriteByte(int v)
{
	unsigned char c = v;
	int ret = m_file.Write(&c, 1);
	assert(ret == 1);
}

void CFileStream::WriteShortLE(int v)
{
	unsigned char c[2];
	c[1] = v >> 8;
	c[0] = v;
	int ret = m_file.Write(&c, 2);
	assert(ret == 2);
}

void CFileStream::WriteIntLE(int v)
{
	unsigned char c[4];
	c[3] = v >> 24;
	c[2] = v >> 16;
	c[1] = v >> 8;
	c[0] = v;
	int ret = m_file.Write(&c, 4);
	assert(ret == 4);
}

void CFileStream::WriteShortBE(int v)
{
	unsigned char c[2];
	c[0] = v >> 8;
	c[1] = v;
	int ret = m_file.Write(&c, 2);
	assert(ret == 2);
}

void CFileStream::WriteIntBE(int v)
{
	unsigned char c[4];
	c[0] = v >> 24;
	c[1] = v >> 16;
	c[2] = v >> 8;
	c[3] = v;
	int ret = m_file.Write(&c, 4);
	assert(ret == 4);
}

void CFileStream::Close()
{
	m_file.Close();
}

CMemoryStream::CMemoryStream(void *buf, int length)
{
	m_data = (unsigned char*)buf;
	m_current = m_data;
	m_length = length;
	m_needFreeBuffer = false;
}

CMemoryStream::CMemoryStream(int length/*, MemoryType memType*/)
{
	m_data = NEW unsigned char[length];
	m_current = m_data;
	m_length = length;
	m_needFreeBuffer = true;
}

CMemoryStream::CMemoryStream(const char* fileName)
{
}

CMemoryStream::~CMemoryStream()
{
	Close();
}

int CMemoryStream::GetLength()
{
	return m_length;
}

int CMemoryStream::GetPosition()
{
	return (int)(m_current - m_data);
}

bool CMemoryStream::IsReadOnly()
{
	//always read-write
	return false;
}

int CMemoryStream::Write(const void* pBuffer, int length)
{
	assert(m_current + length <= m_data + m_length);
	memcpy(m_current, pBuffer, length);
	m_current += length;
	return length;
}

void CMemoryStream::WriteByte(int v)
{
	assert(m_current < m_data + m_length);
	*m_current++ = v;
}

void CMemoryStream::WriteShortLE(int v)
{
	assert(m_current + 2 <= m_data + m_length);
	*m_current++ = v;
	*m_current++ = v >> 8;
}

void CMemoryStream::WriteIntLE(int v)
{
	assert(m_current + 4 <= m_data + m_length);
	*m_current++ = v;
	*m_current++ = v >> 8;
	*m_current++ = v >> 16;
	*m_current++ = v >> 24;
}

void CMemoryStream::WriteShortBE(int v)
{
	assert(m_current + 2 <= m_data + m_length);
	*m_current++ = v >> 8;
	*m_current++ = v;
}

void CMemoryStream::WriteIntBE(int v)
{
	assert(m_current + 4 <= m_data + m_length);
	*m_current++ = v >> 24;
	*m_current++ = v >> 16;
	*m_current++ = v >> 8;
	*m_current++ = v;
}

void CMemoryStream::Close()
{
	if(m_needFreeBuffer)
	{
		SAFE_DELETE_ARRAY(m_data);
	}
}

bool CMemoryStream::Skip(int len)
{
	m_current += len;
	assert(m_current >= m_data && m_current <= m_data + m_length);
	return true;
}

bool CMemoryStream::SetPosition(int pos)
{
	assert(pos < m_length);
	m_current = m_data + pos;
	return true;
}

int CMemoryStream::Read(void* pBuffer, int length)
{
	assert(m_current + length <= m_data + m_length);
	memcpy(pBuffer, m_current, length);
	m_current += length;
	return length;
}

signed char CMemoryStream::ReadByte()
{
	assert(m_current < m_data + m_length);
	return (signed char)*m_current++;
}

unsigned char CMemoryStream::ReadUByte()
{
	assert(m_current < m_data + m_length);
	return (unsigned char)*m_current++;
}

short CMemoryStream::ReadShortLE()
{
	assert(m_current + 2 <= m_data + m_length);
	short r = (short)((m_current[1] << 8) | m_current[0]);
	m_current += 2;
	return r;
}

unsigned short CMemoryStream::ReadUShortLE()
{
	assert(m_current + 2 <= m_data + m_length);
	unsigned short r = (unsigned short)((m_current[1] << 8) | m_current[0]);
	m_current += 2;
	return r;
}

int CMemoryStream::ReadIntLE()
{
	assert(m_current + 4 <= m_data + m_length);
	int r = (m_current[3] << 24) | (m_current[2] << 16) | (m_current[1] << 8) | m_current[0];
	m_current += 4;
	return r;
}

unsigned int CMemoryStream::ReadUIntLE()
{
	assert(m_current + 4 <= m_data + m_length);
	unsigned int r = (m_current[3] << 24) | (m_current[2] << 16) | (m_current[1] << 8) | m_current[0];
	m_current += 4;
	return r;
}

short CMemoryStream::ReadShortBE()
{		
	assert(m_current + 2 <= m_data + m_length);
	short r = (short)((m_current[0] << 8) | m_current[1]);
	m_current += 2;
	return r;
}

unsigned short CMemoryStream::ReadUShortBE()
{
	assert(m_current + 2 <= m_data + m_length);
	unsigned short r = (unsigned short)((m_current[0] << 8) | m_current[1]);
	m_current += 2;
	return r;
}

int CMemoryStream::ReadIntBE()
{
	assert(m_current + 4 <= m_data + m_length);
	int r = (m_current[0] << 24) | (m_current[1] << 16) | (m_current[2] << 8) | m_current[3];
	m_current += 4;
	return r;
}

unsigned int CMemoryStream::ReadUIntBE()
{
	assert(m_current + 4 <= m_data + m_length);
	unsigned int r = (m_current[0] << 24) | (m_current[1] << 16) | (m_current[2] << 8) | m_current[3];
	m_current += 4;
	return r;
}

//char* CMemoryStream::readUTF(MemoryType memType)
//{
//	unsigned short len = ReadUShortBE();
//	char* str = NEW(memType) char[len + 1];
//	str[Read(str, len)] = 0;
//	return str;
//}
